<template>
  <div>
    <uploader :autoStart="false" :options="options" :file-status-text="statusText" class="uploader-example"
      @file-complete="fileComplete" @complete="complete" @file-success="fileSuccess" @files-added="filesAdded">
      <uploader-unsupport></uploader-unsupport>
      <uploader-drop>
        <p>将文件拖放到此处以上传</p>
        <uploader-btn>选择文件</uploader-btn>
        <!-- <uploader-btn :attrs="attrs">选择图片</uploader-btn> -->
        <!-- <uploader-btn :directory="true">选择文件夹</uploader-btn> -->
      </uploader-drop>
      <!-- 上传提示 -->
      <div style="margin-bottom: 5px;" class="el-upload__tip">
        请上传
        <template> 大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b> </template>
        <template> 格式为 <b style="color: #f56c6c">{{ acceptType.toString() }}</b> </template>
        的文件
      </div>
      <uploader-list></uploader-list>
      <!-- <uploader-files></uploader-files> -->
    </uploader>
    <br />
    <div style="margin-left: 10px">
      <el-button @click="allStart()" :disabled="disabled" size="small" type="primary" round icon="el-icon-video-play">
        全部开始
      </el-button>
      <el-button @click="allStop()" style="margin-left: 4px" size="small" type="warning" round
        icon="el-icon-video-pause">全部暂停
      </el-button>
      <el-button @click="allRemove()" style="margin-left: 4px" size="small" type="danger" round icon="el-icon-delete">
        全部移除
      </el-button>
    </div>
  </div>
</template>

<script>
  import axios from "axios";
  import SparkMD5 from "spark-md5";
  import {
    getToken
  } from "@/utils/auth";

  export default {
    data() {
      return {
        skip: false,
        options: {
          //目标上传 URL，默认POST
          target: process.env.VUE_APP_BASE_API + "/system/upload/chunk",
          //分块大小(单位：字节)
          chunkSize: '2048000',
          // 开启服务端分片校验功能
          testChunks: true,
          //上传文件时文件内容的参数名，对应chunk里的Multipart对象名，默认对象名为file
          fileParameterName: 'file',
          //失败后最多自动重试上传次数
          maxChunkRetries: 3,
          parseTimeRemaining: function(timeRemaining, parsedTimeRemaining) {
            return parsedTimeRemaining
              .replace(/\syears?/, "年")
              .replace(/\days?/, "天")
              .replace(/\shours?/, "小时")
              .replace(/\sminutes?/, "分钟")
              .replace(/\sseconds?/, "秒");
          },
          // 服务器分片校验函数
          checkChunkUploadedByResponse: (chunk, message) => {
            const result = JSON.parse(message);
            if (result.data.skipUpload) {
              this.skip = true;
              return true;
            }
            return (result.data.uploaded || []).indexOf(chunk.offset + 1) >= 0;
          },
          headers: {
            // 在header中添加的验证，请根据实际业务来
            "Authorization": "Bearer " + getToken(),
          },
        },
        attrs: {
          accept: "image/*",
        },
        statusText: {
          success: "上传成功",
          error: "上传出错了",
          uploading: "上传中...",
          paused: "暂停中...",
          waiting: "等待中...",
          cmd5: "计算文件MD5中...",
        },
        fileList: [],
        disabled: true
      };
    },
    watch: {
      fileList(o, n) {
        this.disabled = false;
      },
    },
    props: {
      //文件类型，image，video，audio，document
      // {
      //   image: ['gif', 'jpg', 'jpeg', 'png', 'bmp', 'webp'],
      //   video: ['mp4', 'm3u8', 'rmvb', 'avi', 'swf', '3gp', 'mkv', 'flv'],
      //   audio: ['mp3', 'wav', 'wma', 'ogg', 'aac', 'flac'],
      //   document: ['doc', 'txt', 'docx', 'pages', 'epub', 'pdf', 'numbers', 'csv', 'xls', 'xlsx', 'keynote', 'ppt',
      //     'pptx'
      //   ]
      // }
      acceptType: {
        type: Array,
        default: () => ['gif', 'jpg', 'jpeg', 'png', 'bmp', 'webp']
      },
      fileSize: {
        type: Number,
        default: 100
      },
    },
    methods: {
      fileSuccess(rootFile, file, response, chunk) {
        // console.log(rootFile);
        // console.log(file);
        // console.log(message);
        // console.log(chunk);
        const result = JSON.parse(response);
        console.log(result.code, this.skip);

        if (result.code === 200 && !this.skip) {
          axios
            .post(
              process.env.VUE_APP_BASE_API + "/system/upload/merge", {
                identifier: file.uniqueIdentifier,
                filename: file.name,
                totalChunks: chunk.offset,
              }, {
                headers: {
                  "Authorization": "Bearer " + getToken()
                }
              }
            )
            .then((res) => {
              if (res.data.code === 200) {
                console.log("上传成功");
                this.$emit('uploadFileList', res.data.data)
              } else {
                console.log(res);
              }
            })
            .catch(function(error) {
              console.log(error);
            });
        } else {
          console.log("上传成功，不需要合并");
        }
        if (this.skip) {
          this.skip = false;
        }
      },
      fileComplete(rootFile) {
        // 一个根文件（文件夹）成功上传完成。
        // console.log("fileComplete", rootFile);
        // console.log("一个根文件（文件夹）成功上传完成。");
      },
      complete() {
        // 上传完毕。
        // console.log("complete");
      },
      filesAdded(file, fileList, event) {
        var allCheck = true
        file.forEach((e) => {
          const isFormat = this.checkExtensions(e.name, this.acceptType); // 文件格式判断
          if (!isFormat) {
            e.ignored = true; // 过滤文件
            e.cancel(); // 停止上传
            allCheck = false;
            return false;
          }
          // 文件大小判断
          const isSize = this.checkSize(e.size);
          if (!isSize) {
            e.ignored = true; // 过滤文件
            e.cancel(); // 停止上传
            allCheck = false;
            return false;
          } else {
            this.fileList.push(e);
          }
        });
        if (allCheck) {
          this.fileList.forEach(e => {
            this.computeMD5(e); // md5验证
          })
        } else {
          this.fileList = []
        }
      },
      // 检查文件大小
      checkSize(fileSize) {
        var isSize = fileSize / 1024 / 1024 < this.fileSize; // 单位(M)
        if (!isSize) {
          this.$message.warning(
            " 文件大小不能大于" + this.fileSize + "M!"
          );
          return false;
        }
        return true;
      },
      // extensions 允许上传的格式
      checkExtensions(fileName, extensions) {
        console.log("file: ", fileName);
        var format = fileName
          .split(".")
          .pop()
          .toLowerCase(); // 用户上传的文件格式

        // 把允许上传文件格式的数组转为字符串
        var s = extensions.join(",");
        var exp = new RegExp(format);
        if (!exp.test(extensions)) {
          this.$message.warning("请上传 " + s + " 的格式!");
          return false;
        }
        return true;
      },
      computeMD5(file) {
        let fileReader = new FileReader();
        let time = new Date().getTime();
        let blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
        let currentChunk = 0;
        const chunkSize = 1024 * 1024;
        let chunks = Math.ceil(file.size / chunkSize);
        let spark = new SparkMD5.ArrayBuffer();
        // 文件状态设为"计算MD5"
        file.cmd5 = true; //文件状态为“计算md5...”
        file.pause();
        loadNext();
        fileReader.onload = (e) => {
          spark.append(e.target.result);
          if (currentChunk < chunks) {
            currentChunk++;
            loadNext();
            // 实时展示MD5的计算进度
            console.log(`第${currentChunk}分片解析完成, 开始第${currentChunk + 1} / ${chunks}分片解析`);
          } else {
            let md5 = spark.end();
            console.log(
              `MD5计算完毕：${file.name} \nMD5：${md5} \n分片：${chunks} 大小:${file.size} 用时：${new Date().getTime() - time} ms`
            );
            spark.destroy(); //释放缓存
            file.uniqueIdentifier = md5; //将文件md5赋值给文件唯一标识
            file.cmd5 = false; //取消计算md5状态
            file.resume(); //开始上传
          }
        };
        fileReader.onerror = function() {
          this.$message.error(`文件${file.name}读取出错，请检查该文件`);
          file.cancel();
        };

        function loadNext() {
          let start = currentChunk * chunkSize;
          let end = start + chunkSize >= file.size ? file.size : start + chunkSize;
          fileReader.readAsArrayBuffer(blobSlice.call(file.file, start, end));
        }
      },
      allStart() {
        console.log(this.fileList);
        this.fileList.map((e) => {
          if (e.paused) {
            e.resume();
          }
        });
      },
      allStop() {
        console.log(this.fileList);
        this.fileList.map((e) => {
          if (!e.paused) {
            e.pause();
          }
        });
      },
      allRemove() {
        this.fileList.map((e) => {
          e.cancel();
        });
        this.fileList = [];
      },
    },
  };
</script>

<style>
  .uploader-example {
    width: 100%;
    padding: 15px;
    margin: 0px auto 0;
    font-size: 12px;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.4);
  }

  .uploader-example .uploader-btn {
    margin-right: 4px;
  }

  .uploader-example .uploader-list {
    max-height: 440px;
    overflow: auto;
    overflow-x: hidden;
    overflow-y: auto;
  }
</style>